package smr.test;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import client.conf.ServerEnvironment;
import client.extension.utils.FileUtils;

import com.google.gson.Gson;

/**
 * @author tanggf(2012-2-29)
 *
 */
public class Running {
	private static Logger logger;
	
	public static void main(String[] args) throws Exception {	
		//程序执行根目录
		String userDir = System.getProperty("user.dir");
		String configPath = FileUtils.combinePath(userDir, "config");
		//初始化日志配置信息
		initLogger(configPath);			
		
		if(logger.isDebugEnabled()){
			logger.debug("current directory is: {}", userDir);
		}		
		
		String configFile = FileUtils.combinePath(configPath, "config.json");		
		ServerEnvironment.environment.load(configFile);	
		
		String configJson = FileUtils.readAllText(new File(configFile));
		if(logger.isDebugEnabled()){
			logger.debug("the configuration info: {}", configJson);
		}				
		
		Gson gson = new Gson();
		TestConfig config = gson.fromJson(configJson, TestConfig.class);
		if(config.isProxySet()){			
			System.getProperties().put("proxySet", "true");
			System.getProperties().setProperty("http.proxyHost", config.getProxyHost());
			System.getProperties().setProperty("http.proxyPort", config.getProxyPort());
		}				
		
		String urlFile = FileUtils.readAllText(new File(FileUtils.combinePath(configPath, "url.text")));			
		
		String[] urls = urlFile.split("\n|\r\n");	
		int clientCount = config.getClientCount() > 0 ? config.getClientCount() : 1;	
		int max = clientCount > urls.length ? urls.length : clientCount;
		
		//启动线程
		logger.info("ready to start up " + max + " virtual client thread.");		
		//线程进行列表
		List<Progress> progresses = new ArrayList<Progress>();
		Set<String> usings = new HashSet<String>();
		
		//开启线程
		for (int i = 0; i < max; ) {
			String url = getRandonUrl(urls);
			url = url.trim();
			if(url.startsWith("http://") && ! usings.contains(url)){
				usings.add(url);
				if(config.isVideoFile()){
					new Thread(new ShortFilmHandlerTest(url, config, progresses)).start();
				}else{
					new Thread(new AudioHandlerTest(url, config, progresses)).start();
				}				
				i++;
			}			
		}			
		
		//循环等待
		doLoop(config, progresses);
		
		//结束循环, 汇总信息
		summary(progresses, config);
	}
	
	private static void initLogger(String configPath) {
		LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
		JoranConfigurator configurator = new JoranConfigurator();
		configurator.setContext(lc);
		lc.reset();
		File configFile = new File(FileUtils.combinePath(configPath, "logback.xml"));
		try {
			configurator.doConfigure(configFile);
		} catch (JoranException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		logger = LoggerFactory.getLogger(Running.class);
	}

	private static void doLoop(TestConfig config, List<Progress> progresses) throws Exception{		
		int delay = config.isVideoFile() ? 10 : 20;
		int round = 0;
		logger.info("=======start to loop, be patient=======");
		while(true){
			round++;
			Thread.sleep(1000 * delay);						
			int size = progresses.size();
			int done = 0;		
			for (Progress progress : progresses) {
				if(progress.isDone() || progress.isFail()){
					done++;
				}else{			
					if(progress.isStartDownload()){
						String message = progress.getInfo() +", total content length[" + progress.getTotal() + "], downloaded[" + progress.getDownloaded() + "], percent[" + progress.getPercent() + "]";
						logger.info(message);
					}else{
						logger.info("the server STILL parsing the url[" + progress.getPageUrl() + "]");
					}					
				}
			}
			if(done == size){
				break;
			}
			logger.info("==============Patient Round(" + round + ")=================");	
		}
	}

	private static void summary(List<Progress> progresses, TestConfig config) {
		//总进程数量	
		int size = progresses.size();
		//成功个数
		int done = 0;
		//解析总时间(秒)
		int totalParseTime = 0;
		//下载总时间(秒)
		int totalDownloadTime = 0;
		
		logger.info("======information summary======");						
		
		for (Progress progress : progresses) {
			if(progress.isDone()){
				logger.info(progress.summary());
				done++;
				totalParseTime += progress.getParseTime();
				totalDownloadTime += progress.getDownloadTime();
			}else{
				logger.error(progress.getMsg());					
			}
		}
		
		logger.info("You have opened " + size + " Thread, and " + done + " successes, " + (size - done) + " fails");
		if(done > 0){
			logger.info("average parse time is: " + totalParseTime/done + "seconds.");
			if(config.isDownloadFile()){
				logger.info("average download time is: " + totalDownloadTime/done + "seconds");
			}
		}		
	}
	

	private static String getRandonUrl(String[] urls) {
		int length = urls.length;
		Random random = new Random();
		return urls[random.nextInt(length)];			
	}
}
